#include "iot13v.h"

#define SMI_DIR     DDRB
#define SMI_OUT     PORTB
#define SMI_IN      PINB
#define MDIO        0b00000001
#define MDC         0b00000010
#define KEY_IN      0b00100000
#define KEY_OUT     0b00001000

#define WDRF_NEW    0b00001000
#define WDTIF_NEW   0b10000000
#define WDTIE_NEW   0b01000000
#define WDCE_NEW    0b00010000
#define WDE_NEW     0b00001000
#define WDP_1SEC    0b00000111
#define WDP_2SEC    0b00001000
#define WDP_4SEC    0b00100000
#define WDP_8SEC    0b00100001
/*******************************************************************/
/*                         function declare                        */
/*******************************************************************/
void SMI_1(void);
void SMI_0(void);
void Delay(unsigned int delay);
//PCIE interrupt program
#pragma interrupt_handler Switch:3 


/*******************************************************************/
/*                         function  phototype                     */
/*******************************************************************/
void RTL8309_Write(unsigned char phy_add,unsigned char reg_add,unsigned int data)
{
  unsigned int i;
  asm("cli");      //interrupt disabled
  for(i=0;i<32;i++)//send preamble,32 1
    {
      SMI_1();
    }
  {//01            //send start
    SMI_0();
    SMI_1();
  }
  {//01            //send op code,write
    SMI_0();
    SMI_1();
  }
  for(i=0;i<5;i++)//send phy address
    {
      if(phy_add&0x10)
        SMI_1();//1
      else
        SMI_0();//0
      phy_add<<=1;
     }
   for(i=0;i<5;i++)//send reg address
    {
      if(reg_add&0x10)
        SMI_1();//1
      else
        SMI_0();//0
      reg_add<<=1;
     }
   
  {//10           //send turn around
    SMI_1();//1 
    SMI_0();//0
  }
  for(i=0;i<16;i++)//send data
    {
      if(data&0x8000)
        SMI_1();//1
      else
        SMI_0();//0
      data<<=1;
    }
  asm("sei");     //interrupt enabled
}
//SMI send 1
void SMI_1(void) 
{
  SMI_OUT|=MDIO;
  asm("nop");
  asm("nop");
  SMI_OUT|=MDC;
  asm("nop");
  asm("nop");
  SMI_OUT&=~MDC;
  asm("nop");
  asm("nop");
}
//SMI send 0
void SMI_0(void)  
{
  SMI_OUT&=~MDIO;
  asm("nop");
  asm("nop");
  SMI_OUT|=MDC;
  asm("nop");
  asm("nop");
  SMI_OUT&=~MDC;
  asm("nop");
  asm("nop");
}
//PCIE interrupt program
void Switch()
{
  asm("cli");   //interrupt disabled
  if((SMI_IN&KEY_IN)==0) //KEY_IN falling edge
    {
	  Delay(10000);
	  if((SMI_IN&KEY_IN)==0)//delay to get rid of key dithering
	    {
		  RTL8309_Write(1,24,0b0000111000100010);  //1<-->5
		  RTL8309_Write(2,24,0b0000111001001000);  //3<-->6
		}
	 }
  if((SMI_IN&KEY_OUT)==0) //KEY_OUT falling edge
    {
	  Delay(10000);
	  if((SMI_IN&KEY_OUT)==0)//delay to get rid of key dithering
	    {
		  RTL8309_Write(1,24,0b0000111000100100);  //1<-->5
		  RTL8309_Write(2,24,0b0000111001010000);  //3<-->6
		}
	}
  asm("sei");  //interrupt enabled
}
//delay 
void Delay(unsigned int delay)
{
  unsigned int delay_i;
  for(delay_i=0;delay_i<delay;delay_i++)
  {
    asm("nop");
  }
}

/*******************************************************************/
/*                         main function                           */
/*******************************************************************/
void main( void )
{
  unsigned char j;
  //watchdog setup
  
  //delay more than 3 second
  for(j=0;j<20;j++)
    {
	  Delay(60000);
	  asm("wdr");                          //reset watchdog counter
	}
  MCUSR&=~WDRF_NEW;                       //clear watchdog reset flag
  WDTCR|=WDCE_NEW+WDE_NEW;                //watchdog start timing
  WDTCR|=WDE_NEW+WDP_1SEC;                //setup delay time: 1 second
  //I/O setup
  SMI_DIR|=MDC+MDIO;                      //set MDIO and MDC output
  SMI_DIR&=~(KEY_IN+KEY_OUT);             //set KEY_IN and KEY_OUT input
  SMI_OUT|=KEY_IN+KEY_OUT;                //set KEY_IN and KEY_OUT input
  SMI_OUT&=~MDC;                          //MDC output low to get rising edge later
  SMI_OUT&=~MDIO;                         //MDIO output low , not necessary
  //PHY1 init
  //RTL8309_Write(0,16,0b1110010001111100);  //REG16 setup,global control 0
  //RTL8309_Write(1,24,0b0000111001000010);  //control 2 and VLAN entry,VLAN B cleared
  //PHY2 init
  RTL8309_Write(2,4, 0b0000000000000001);  //REG4 setup,Auto negotiation
  RTL8309_Write(2,0, 0b0011001100000000);  //control,restart Auto negotiation
  //PHY3 init
  //RTL8309_Write(3,24,0b0000111000101000);
  //PHY4 init
  RTL8309_Write(4,4, 0b0000000000000001);  //REG4 setup,Auto negotiation
  RTL8309_Write(4,0, 0b0011001100000000);  //control,restart Auto negotiation
  //PHY5 init
 // RTL8309_Write(5,24,0b0000111000101000);
  //PHY6 init
 // RTL8309_Write(6,24,0b0000111001000010);  //control 2 and VLAN entry,VLAN B cleared
  GIMSK|=0b00100000;                       //PCINT0 interrupt enabled
  PCMSK|=0b00101000;                       //PCINT3 and PCINT5 interrupt enabled
  //interrupt disabled
  asm("sei");                              //interrupt enabled
  //wait for interrupt
  while(1)
  {
    asm("nop");
	asm("nop");
    asm("nop");
	asm("wdr")                             //reset watchdog counter
	asm("nop");
	asm("nop");
    asm("nop");
  }
}

